//
//  InsCcMeasuresModel.swift
//  ParsingCC
//
//  Created by ins-yangming on 2023/2/28.
//

import UIKit
import SwiftyJSON

class InsCcMeasuresModel: NSObject {
    
    var measureIndex : Int = 0;
    
    
    var w = 0.0;
    
    var staves = [InsCcStavesModel]();
    
    var voices = [InsCcVoiceModel]();
    
    var fifths = 0;
    
    var changeNoteFifths = 0;
    
    var cancel = false;
    
    var beats = 0;
    
    var beatType = 0;
    
    var measureDuration = 4.0;
    
    var json = JSON();
    
    var nextClef = "";
    var nextStaff = 0;
    
    
    
    var slurStopx = 0.0;
    var slurStaff = 0;
    
    var location = "";
    
    var endM1 = 0;
    var endM2 = 0;
    var endNumber = "";
    
    var barStyle = "";
    var direction = "";
    
    var segnoType = 0;
    var segnoStaff = 0;
    
    var metronome = "";
    
    var nextGlissandos = [(Double , Int , Int)]();
    
    var shiftArray = [(ShmOctaveShiftModel , ShmOctaveShiftModel)]();
    
    var wedgeArray = [(ShmWedgeModel , ShmWedgeModel)]();
    
    init(json : JSON , measureDuration : Double , index : Int , changeNoteFifths : Int) {
        super.init();
        self.json = json;
        self.changeNoteFifths = changeNoteFifths;
        self.measureIndex = index;
        
        self.w = json["w"].doubleValue;
//        if var noteDic = json["notes"].array?.first {
//            let note = InsCcNote(json: noteDic);
//            self.w -= note.x;
//        }
        
        for i in 0..<json["staves"].intValue {
            let stave = InsCcStavesModel();
            stave.staveIndex = i + 1;
            self.staves.append(stave);
        }
        
        
        
        if let fifths = json["fifths"].dictionary?["fifths"]?.intValue {
            self.fifths = fifths;
            if fifths != 0 {
                self.changeNoteFifths = self.fifths;
            }
            
            self.cancel = ((json["fifths"].dictionary?["cancel"]?.intValue ?? 0) > 0);
        }
        
        if let beats = json["time"].dictionary?["beats"]?.intValue {
            self.beats = beats;
        }
        
        if let beatu = json["time"].dictionary?["beatu"]?.intValue {
            self.beatType = beatu;
        }
        if let lbar = json["lbar"].dictionary , lbar.count != 0 {
            self.location = "left";
        }
        if let rbar = json["rbar"].dictionary , rbar.count != 0 {
            self.location = "right";
        }
        
        if let type = json["lbar"].dictionary?["type"]?.stringValue {
            self.barStyle = type;
        }
        if let repeatString = json["lbar"].dictionary?["repeat"]?.stringValue {
            self.direction = repeatString;
            self.location = "left";
        }
        if let type = json["rbar"].dictionary?["type"]?.stringValue {
            self.barStyle = type;
        }
        if let repeatString = json["rbar"].dictionary?["repeat"]?.stringValue {
            self.direction = repeatString;
            self.location = "right";
        }
        
        if let ends = json["ends"].dictionary {
            self.endM1 = (ends["m1"]?.intValue ?? 0) + 1;
            self.endM2 = (ends["m2"]?.intValue ?? 0) + 1;
            self.endNumber = ends["num"]?.stringValue ?? "";
        }
        if self.beats == 0 && self.beatType == 0 && index == 0 {
            self.beats = 4;
            self.beatType = 4;
        }
        
        self.measureDuration = measureDuration;
        
        if self.beats != 0 && self.beatType != 0 {
            self.measureDuration = 4/Double(self.beatType) * Double(self.beats);
        }
        if self.measureIndex == 18 {
            print("111");
        }
        if let notes = json["notes"].array {
            var stave = staves.first;
            var notesArray = [InsCcNote]();
            a : for (i , json) in notes.enumerated() {
                let note = InsCcNote(json: json);
                note.index = i;
                
                if i == 0 {
                    let voice = InsCcVoiceModel();
                    voice.notes.append(note);
                    voice.voiceIndex = note.v;
                    stave?.voices.append(voice);
                    self.voices.append(voice);
                }else if (((note.staff != notesArray[notesArray.count - 1].staff) || (note.v != notesArray[notesArray.count - 1].v))) {
                    var isHaveVoice = false;
                    for staveModel in staves {
                        if staveModel.staveIndex == note.staff {
                            stave = staveModel;
                        }
                    }
                    if let voices = stave?.voices {
                        for voice in voices {
                            if voice.voiceIndex == note.v {
                                voice.notes.append(note);
                                isHaveVoice = true;
                                break;
                            }
                        }
                    }
                    
                    
                    if !isHaveVoice {
                        let voice = InsCcVoiceModel();
                        voice.notes.append(note);
                        voice.voiceIndex = note.v;
                        stave?.voices.append(voice);
                        self.voices.append(voice);
                    }
                }else{
                    stave?.voices.last?.notes.append(note);
                }
                notesArray.append(note);
                
                var noteNames = [String]();
                if self.changeNoteFifths > 0 {
                    noteNames = ["F","C","G","D","A","E","B"];
                }else{
                    noteNames = ["B","E","A","D","G","C","F"];
                }
                var selectedArray: [String] = []
                
                // 取数组的前 fifths 个元素
                for i in 0..<min(abs(self.changeNoteFifths), noteNames.count) {
                    selectedArray.append(noteNames[i]);
                }
                let steps = ["C","D","E","F","G","A","B"];
                if selectedArray.contains(steps[note.step]) {
                    if self.changeNoteFifths > 0  && note.alter != 1 {
                        note.alter = 1;
                    }else if self.changeNoteFifths < 0  && note.alter != -1 {
                        note.alter = -1;
                    }
                    if note.accidental == "natural" {
                        note.alter = 0;
                    }
//                    else if note.accidental == "Flat" {
//                        note.alter -= 1;
//                    }else if note.accidental == "Sharp" {
//                        note.alter += 1;
//                    }
                }
                
                for chordNote in note.chordNotes {
                    if selectedArray.contains(steps[chordNote.step]) && chordNote.alter == 0 {
                        if self.changeNoteFifths > 0 {
                            chordNote.alter = 1;
                        }else{
                            chordNote.alter = -1;
                        }
                        if chordNote.accidental == "natural"{
                            chordNote.alter = 0;
                        }
                    }
                }
                
            }
            
            
            for voice in self.voices {
                voice.notes = voice.notes.sorted(by: { note1, note2 in
                    return note1.x < note2.x;
                })
            }
        
            
            var removeArray = [InsCcVoiceModel]();
            for (i , voices) in self.voices.enumerated() {
                if i < self.voices.count - 1 {
                    let nextVoices = self.voices[i + 1];
                    // 获取 array1 中覆盖的 x 坐标范围
                    var coveredRanges: [(Int, Int)] = []
                    var coveredRanges2: [(Int, Int)] = []
                    var i = 0
                    while i < voices.notes.count {
                        var note = voices.notes[i];
                        while i + 1 < voices.notes.count {
                            var note2 = voices.notes[i];
                            var note1 = voices.notes[i + 1];
                            if abs(note1.tick - note2.tick - Int(note2.duration * 480)) > 30 {
                                coveredRanges.append((note.tick, (note1.tick + Int(note1.duration * 480))))
                                break;
                            }
                            i += 1
                        }
                        i += 1
                        
                    }
                    
                    i = 0
                    while i < nextVoices.notes.count {
                        var note = nextVoices.notes[i];
                        while i + 1 < nextVoices.notes.count {
                            var note2 = nextVoices.notes[i];
                            var note1 = nextVoices.notes[i + 1];
                            if abs(note1.tick - note2.tick - Int(note2.duration * 480)) > 30 {
                                coveredRanges2.append((note.tick, (note1.tick + Int(note1.duration * 480))))
                                break;
                            }
                            i += 1
                        }
                        i += 1
                        
                    }
                    
//                    print("合并后的数组: \(1)")
                    
                    if let lastNote = voices.notes.last {
                        if let firstNote = nextVoices.notes.first {
                            if abs(lastNote.tick + Int(lastNote.duration * 480) - firstNote.tick) < 30 {
                                voices.notes.append(contentsOf: nextVoices.notes);
                                voices.moreDirections.append(contentsOf: nextVoices.moreDirections);
                                voices.directions.append(contentsOf: nextVoices.directions);
                                nextVoices.notes.removeAll();
                                removeArray.append(nextVoices);
                                voices.notes.sorted { note1, note2 in
                                    return note1.x < note2.x;
                                }
                            }
                        
                            

//                            // 检查 array2 是否与 array1 覆盖的范围重叠
//                            var isOverlapping = false
//                            for (start, end) in coveredRanges {
//                                for (start, end) in coveredRanges2 {
//                                    if element >= start && element <= end {
//                                        isOverlapping = true
//                                        break
//                                    }
//                                }
//                                if isOverlapping {
//                                    break
//                                }
//                            }
//
//                            // 如果不重叠，则将 array2 合并到 array1 中
//                            if !isOverlapping {
//                                array1.append(contentsOf: array2)
//                            }
//
                            
//

                        }
                    }
                }
            }
            
            for voice in self.voices {
                if removeArray.contains(voice) {
                    if let index = self.voices.firstIndex(of: voice) {
                        self.voices.remove(at: index);
                    }
                }
            }
            for stave in self.staves {
                for voice in stave.voices {
                    if removeArray.contains(voice) {
                        if let index = stave.voices.firstIndex(of: voice) {
                            stave.voices.remove(at: index);
                        }
                    }
                }
            }
          
            
            for voice in self.voices {
                for (i , note) in voice.notes.enumerated() {
                    if i != voice.notes.count - 1 {
                        let nextNote = voice.notes[i + 1];
                        if nextNote.tick != note.tick {
                            if note.tick + Int(note.duration * 480) - nextNote.tick > 30 && note.isGraceSlash == 0 {
                                note.duration = Double((nextNote.tick - note.tick))/480.0;
                            }
                        }
                    }else {
                        if Double(note.tick + Int(note.duration * 480)) > self.measureDuration * 480  && note.isGraceSlash == 0 {
                            note.duration = self.measureDuration - Double(note.tick)/480.0;
                            if note.duration == 0 {
                                print(1111);
                            }
                        }
                    }
                   
                    for chordNote in note.chordNotes {
                        chordNote.duration = note.duration;
                    }
                }
            }
            
            
            
            //                if self.measureIndex == 13 {
            //                    print(111);
            //                }
            for stave in staves {
                //                stave.voices = stave.voices.sorted { voice1, voice2 in
                //                    voice1.notes = voice1.notes.sorted(by: { note1, note2 in
                //                        return note1.x < note2.x;
                //                    });
                //                    voice2.notes = voice2.notes.sorted(by: { note1, note2 in
                //                        return note1.x < note2.x;
                //                    })
                //                    return voice1.voiceIndex < voice2.voiceIndex;
                //                }
                
                for voice in stave.voices {
                    for (i , note) in voice.notes.enumerated() {
                        if i > 0 {
                            let lastNote = voice.notes[i - 1];
                            if (note.inbeam && lastNote.beamType.count != 0) {
                                for (num , _ , n2) in lastNote.beamType {
                                    if n2 > note.index {
                                        note.beamType.append((num, 1, n2));
                                    }else if n2 == note.index {
                                        note.beamType.append((num, 2, n2));
                                    }
                                }
                                note.beamType = note.beamType.sorted { data1, data2 in
                                    return data1.0 < data2.0;
                                }
                            }
                        }
                        if self.measureIndex == 15 {
                            //                            print("111");
                        }
                        if note.tremoloType == "start"{
                            if note.staff == stave.staveIndex {
                                for j in i..<voice.notes.count {
                                    let stopNote = voice.notes[j];
                                    if stopNote.x > note.tremoloX2 {
                                        stopNote.tremoloType = "stop";
                                        stopNote.tremolo = note.tremolo;
                                        break;
                                    }
                                }
                            }
                        }
                        
                        if note.tuplet > 0 && (!note.isTupletStart && !note.isTupletContinue && !note.isTupletStop) {
                            if i + note.tuplet - 1 < voice.notes.count && note.tuplet >= 3{
                                
                                let lastNote = voice.notes[i + note.tuplet - 1];
                                let allTick = Double(lastNote.tick - note.tick)/Double(note.tuplet - 1) * Double(note.tuplet);
                                
                                let normalNotes = Int(allTick/480.0/note.duration);
                                note.normalNotes = normalNotes;
                                var duration = note.duration / Double(note.tuplet) * Double(note.normalNotes);
                                duration = allTick/Double(note.tuplet)/480.0;
                                for j in 0..<note.tuplet {
                                    voice.notes[i + j].tuplet = note.tuplet;
                                    voice.notes[i + j].duration = duration;
                                    voice.notes[i + j].normalNotes = note.normalNotes;
                                    if j == 0 {
                                        voice.notes[i + j].isTupletStart = true;
                                    }else if j == note.tuplet - 1  {
                                        voice.notes[i + j].isTupletStop = true;
                                    }else{
                                        voice.notes[i + j].isTupletContinue = true;
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        
        if let clefs = json["clefs"].array {
            for clef in clefs {
                if clef["tick"].intValue == Int(self.measureDuration) * 480 {
                    self.nextClef = clef["clef"].stringValue;
                    self.nextStaff = clef["staff"].intValue;
                }else if clef["tick"].intValue == 0 && index == 0 {
                    
                }else{
                    var isFind = false;
                    a : for stave in staves {
                        if clef["staff"].intValue == stave.staveIndex {
                            if let voice = stave.voices.first {
                                for note in voice.notes {
                                    if note.tick >= clef["tick"].intValue {
                                        note.clef = clef["clef"].stringValue;
                                        isFind = true;
                                        break a;
                                    }
                                }
                            }
                        }
                    }
                    if !isFind {
                        self.nextClef = clef["clef"].stringValue;
                        self.nextStaff = clef["staff"].intValue;
                    }
                }
            }
        }
        for stave in staves {
            for v in stave.voices {
                if let lastNote = v.notes.last {
                    if Double(lastNote.tick)/480.0 + lastNote.duration > self.measureDuration {
                        if Double(lastNote.tick)/480.0 < self.measureDuration {
                            lastNote.duration = self.measureDuration - Double(lastNote.tick)/480.0;
                        }
                    }
                }
            }
        }
        
        if self.measureIndex == 0 {
            print(111);
        }
        if let pdirs = json.dictionary?["pdirs"]?.array {
            
            for pdir in pdirs {
                if let type = pdir.dictionary?["type"]?.string , type.count != 0 {
                    if type == "shift" {
                        let shiftSize = pdir.dictionary?["size"]?.intValue ?? 0;
                        let shiftStopx = (pdir.dictionary?["stopx"]?.doubleValue ?? 0) + 0.05;
                        let shiftX1 = (pdir.dictionary?["x1"]?.doubleValue ?? 0) - 0.05;
                        let shiftStaff = pdir.dictionary?["staff"]?.intValue ?? 0;
                        let shiftVoice = (pdir.dictionary?["voice"]?.intValue ?? 0) + 1;
                        let isUp = pdir.dictionary?["up"]?.boolValue ?? false;
                        
                        a : for stave in staves {
                            if stave.staveIndex == shiftStaff {
                                for voice in stave.voices {
                                    for note in voice.notes {
                                        if note.x >= shiftX1 && note.x <= shiftStopx {
                                            //问题： 有些谱子可能需要重新计算note
                                            
//                                            var step = 7 + note.line;
//                                            var octave = 4;
//                                            while !(step > 0 && step < 8) {
//                                                if step > 7 {
//                                                    step -= 7
//                                                    octave += 1;
//                                                }else if step < 1 {
//                                                    step += 7;
//                                                    octave -= 1;
//                                                }
//                                            }
//                                            note.octave = octave;
//                                            note.step = step;
//                                            if isUp {
//                                                note.octave -= (shiftSize/8);
//                                            }else{
//                                                note.octave += (shiftSize/8);
//                                            }
                                        }
                                    }
                                    if voice.voiceIndex == shiftVoice {
                                        let octaveShiftModel = ShmNoteDirectionModel();
                                        octaveShiftModel.x = shiftX1;
                                        octaveShiftModel.staff = "\(shiftStaff)";
                                        octaveShiftModel.voice = "\(shiftVoice)";
                                        let shift1 = ShmOctaveShiftModel();
                                        octaveShiftModel.octaveShift = shift1;
                                        octaveShiftModel.octaveShift?.type = isUp ? "up" : "down";
                                        octaveShiftModel.octaveShift?.number = "1";
                                        octaveShiftModel.octaveShift?.size = "\(shiftSize)";
                                        octaveShiftModel.octaveShift?.isUp = isUp;
                                        octaveShiftModel.octaveShift?.shiftSize = shiftSize;
                                        voice.directions.append(octaveShiftModel);
                                        
                                        let octaveShiftStopModel = ShmNoteDirectionModel();
                                        octaveShiftStopModel.x = shiftStopx;
                                        octaveShiftStopModel.staff = "\(shiftStaff)";
                                        octaveShiftStopModel.voice = "\(shiftVoice)";
                                        let shift2 = ShmOctaveShiftModel();
                                        octaveShiftStopModel.octaveShift = shift2;
                                        octaveShiftStopModel.octaveShift?.type = "stop";
                                        octaveShiftStopModel.octaveShift?.number = "1";
                                        octaveShiftStopModel.octaveShift?.size = "\(shiftSize)";
                                        octaveShiftStopModel.octaveShift?.isUp = isUp;
                                        octaveShiftStopModel.octaveShift?.shiftSize = shiftSize;
                                        if shiftStopx > self.w {
                                            octaveShiftStopModel.x -= self.w;
                                            voice.moreDirections.append(octaveShiftStopModel);
                                        }else{
                                            voice.directions.append(octaveShiftStopModel);
                                        }
                                        self.shiftArray.append((shift1, shift2));
                                        break a;
                                    }
                                }
                            }
                        }
                    }else if type == "wedge" {
                        let crescendo = (pdir.dictionary?["crescendo"]?.bool ?? false);
                        let staff = pdir.dictionary?["staff"]?.intValue ?? 0;
                        let x1 = pdir.dictionary?["x1"]?.doubleValue ?? 0;
                        let wedgeStopx = pdir.dictionary?["stopx"]?.doubleValue ?? 0;
                        if self.measureIndex == 36 {
                            //                            print(111);
                        }
                        for stave in self.staves {
                            if stave.staveIndex == staff && stave.voices.count != 0 {
                                var voice : InsCcVoiceModel = stave.voices[0];
                                var minx = 10000.0;
                                for v in stave.voices {
                                    for note in v.notes {
                                        if fabs(note.x - x1) < minx {
                                            minx = fabs(note.x - x1);
                                            voice = v;
                                        }
                                    }
                                }
                                let wedgeModel = ShmNoteDirectionModel();
                                wedgeModel.x = x1;
                                wedgeModel.staff = "\(staff)";
                                wedgeModel.placement = "above";
                                let wedge1 = ShmWedgeModel();
                                wedgeModel.wedge = wedge1;
                                var wedge = "";
                                if crescendo {
                                    wedge = "crescendo";
                                }else{
                                    wedge = "diminuendo";
                                }
                                wedgeModel.wedge?.type = wedge;
                                wedgeModel.wedge?.number = "\(stave.staveIndex + 1)";
                                voice.directions.append(wedgeModel);
                                
                                let wedgeStopModel = ShmNoteDirectionModel();
                                wedgeStopModel.x = wedgeStopx;
                                wedgeStopModel.staff = "\(staff)";
                                wedgeStopModel.placement = "above";
                                let wedge2 = ShmWedgeModel();
                                wedgeStopModel.wedge = wedge2;
                                wedgeStopModel.wedge?.type = "stop";
                                wedgeStopModel.wedge?.number = "\(stave.staveIndex + 1)";
                                if wedgeStopx > self.w {
                                    wedgeStopModel.x -= self.w;
                                    voice.moreDirections.append(wedgeStopModel);
                                    //                                    print("wedgeStopModel" , wedgeStopModel.x);
                                }else{
                                    voice.directions.append(wedgeStopModel);
                                }
                                self.wedgeArray.append((wedge1,wedge2));
                                break;
                            }
                        }
                    }
                }
            }
        }
        
        
        if self.measureIndex == 324 {
            //            print(111);
        }
        
        for stave in self.staves {
            for voice in stave.voices {
                for (i , note) in voice.notes.enumerated() {
                    if note.isSlideStart && i + 1 < voice.notes.count {
                        voice.notes[i + 1].isSlideStop = true;
                    }
                    if note.slurStopx > 0 {
                        var isFind = false;
                        for j in (i + 1)..<voice.notes.count {
                            let note2 = voice.notes[j];
                            if j < voice.notes.count - 1 {
                                if abs(note2.x - note.slurStopx) < 15 {
                                    note2.slur = "stop";
                                    isFind = true;
                                    break;
                                }
                            }else{
                                if note.slurStopx < self.w {
                                    note2.slur = "stop";
                                    isFind = true;
                                    break;
                                }
                            }
                        }
                        if note.slurStopx < self.w {
                            voice.notes.last?.slur = "stop";
                            isFind = true;
                        }
                        if note.slurStopx > self.w {
                            self.slurStopx = note.slurStopx - self.w;
                            self.slurStaff = note.staff;
                        }else {
                            if !isFind {
                                //                                print(111);
                            }
                        }
                    }
                    if note.fingeringArray.count != 0 && note.rest {
                        if i + 1 < voice.notes.count && !voice.notes[i + 1].rest {
                            voice.notes[i + 1].fingeringArray = note.fingeringArray;
                            note.fingeringArray.removeAll();
                        }
                    }
                }
            }
        }
        
        
        if self.measureIndex == 37 {
            //            print(111);
        }
        
        for stave in self.staves {
            for voice in stave.voices {
                for (i , note) in voice.notes.enumerated() {
                    if note.isGlissandoStart {
                        if note.glissandoStopX <= self.w {
                            for j in i..<voice.notes.count {
                                if fabs(voice.notes[j].x - note.glissandoStopX) < 20 {
                                    voice.notes[j].isGlissandoStop = true;
                                    break;
                                }
                            }
                        }else{
                            self.nextGlissandos.append((note.glissandoStopX - self.w, voice.voiceIndex, stave.staveIndex));
                        }
                    }
                }
            }
        }
        if self.measureIndex != 0 {
            for stave in self.staves {
                for voice in stave.voices {
                    var newVoice = [InsCcNote]();
                    
                    for (i , note) in voice.notes.enumerated() {
                        if i == 0 {
                            let note = voice.notes[0];
                            if note.tick != 0 {
                                let restNote = InsCcNote(json: JSON());
                                restNote.duration = Double(note.tick) / 480;
                                restNote.staff = note.staff;
                                restNote.v = note.v;
                                restNote.rest = true;
                                let type = Int(4.0/restNote.duration * 10);
                                let typeValues = [10,20,40,80,160,320,640];
                                if typeValues.contains(type) {
                                    restNote.type = type/10;
                                }else if typeValues.contains(Int(4.0/(restNote.duration / 1.5 * 10))) {
                                    restNote.type = Int(4.0/(restNote.duration / 1.5));
                                    restNote.dots = 1;
                                }else {
                                    for value in typeValues {
                                        if value > type {
                                            restNote.type = value;
                                            break;
                                        }
                                    }
                                }
                                if note.clef.count != 0 {
                                    restNote.clef = note.clef;
                                    note.clef = "";
                                }
                                newVoice.append(restNote);
                            }else if self.measureIndex == 0 {
                                let note2 = voice.notes[voice.notes.count - 1];
                                if Double(note2.tick)/480.0 + note2.duration < self.measureDuration - 0.05 {
                                    let time = Int((self.measureDuration - note2.duration) * 480)  - note2.tick;
                                    for note in voice.notes {
                                        note.tick += time;
                                    }
                                    let restNote = InsCcNote(json: JSON());
                                    restNote.duration = Double(time) / 480;
                                    restNote.staff = note.staff;
                                    restNote.v = note.v;
                                    restNote.rest = true;
                                    let type = Int(4.0/restNote.duration * 10);
                                    let typeValues = [10,20,40,80,160,320,640];
                                    if typeValues.contains(type) {
                                        restNote.type = type/10;
                                    }else if typeValues.contains(Int(4.0/(restNote.duration / 1.5 * 10))) {
                                        restNote.type = Int(4.0/(restNote.duration / 1.5));
                                        restNote.dots = 1;
                                    }else {
                                        for value in typeValues {
                                            if value > type {
                                                restNote.type = value;
                                                break;
                                            }
                                        }
                                    }
                                    if note.clef.count != 0 {
                                        restNote.clef = note.clef;
                                        note.clef = "";
                                    }
                                    newVoice.append(restNote);
                                }
                            }
                        }else if Double(note.tick - voice.notes[i - 1].tick)/480 > voice.notes[i - 1].duration  {
                            voice.notes[i - 1].duration = Double(note.tick - voice.notes[i - 1].tick)/480;
                        }
                        newVoice.append(note);
                    }
                    voice.notes = newVoice;
                    
                }
            }
        }
        
        if self.measureIndex == 31 {
//            print(111);
        }
        
        if let dirs = json["dirs"].array {
            for dir in dirs {
                let type = dir["type"].stringValue;
                
                let staff = dir["staff"].intValue;
                let tick = dir["tick"].intValue;
                var text = dir["text"].stringValue;
                
                var bpm = "";
                if text == "Prestissimo" {
                    bpm = "180";
                }else if text == "Vivacissimo" {
                    bpm = "140";
                }else if text == "Allegrissimo" {
                    bpm = "150";
                }else if text == "Presto" {
                    bpm = "160";
                }else if text == "Vivace" {
                    bpm = "120";
                }else if text == "Allegro" {
                    bpm = "120";
                }else if text == "Allegro Moderato" {
                    bpm = "120";
                }else if text == "Allegretto" {
                    bpm = "100";
                }else if text == "Moderato" {
                    bpm = "100";
                }else if text == "Andantino" {
                    bpm = "80";
                }else if text == "Andante" {
                    bpm = "80";
                }else if text == "Adagietto" {
                    bpm = "66";
                }else if text == "Adagio" {
                    bpm = "60";
                }else if text == "Andante moderato" {
                    bpm = "80";
                }else if text == "Grave" {
                    bpm = "50";
                }else if text == "Larghetto" {
                    bpm = "66";
                }else if text == "Lento" {
                    bpm = "60";
                }else if text == "Largo" {
                    bpm = "50";
                }else if text == "Larghissimo" {
                    bpm = "10";
                }else if text == "Marcia moderato" {
                    bpm = "100";
                }else if text == "Poco moto" {
                    bpm = "108";
                }
                //                print("1111" , text);
                if bpm.count != 0 {
                    self.staves.first?.voices.first?.notes.first?.metronome = bpm;
                }
                
                if self.measureIndex == 1 && tick == 0 {
                    let note = self.staves.first?.voices.first?.notes.first;
                    if type == "sym" {
                        self.segnoStaff = dir["staff"].intValue;
                        if text == "segno" {
                            self.segnoType = 1;
                        }else if text == "coda" {
                            //                                            self.segnoType = 2;
                        }
                    }else if type.count == 0 {
                        if text == "D.S. al Coda" {
                            self.segnoType = 2;
                        }else if text == "To Coda" {
                            self.segnoType = 3;
                        }else if text == "Coda" {
                            self.segnoType = 4;
                        }else if text.contains("rit.") {
                            note?.word += text;
                        }else {
                            if text.count > 1 {
                                if NSString(string: text).substring(to: 1) != "." {
                                    if !text.contains("=") {
                                        note?.word += text;
                                    }
                                }
                            }else{
                                note?.word += text;
                            }
                        }
                    }else if type == "metronome" {
                        note?.metronome = dir["value"].stringValue;
                        let textl = dir["textl"].stringValue;
                        if textl.count != 0 {
                            note?.word = textl;
                        }
                        if dir["value"].stringValue.count == 0 && dir["textl"].stringValue.count == 0 {
                            for (i , dir) in dirs.enumerated() {
                                let type = dir["type"].stringValue;
                                let text = dir["text"].stringValue;
                                if type.count == 0 && text.contains("=") {
                                    note?.metronome = text.replacingOccurrences(of: "=", with: "").replacingOccurrences(of: " ", with: "");
                                    break;
                                }
                            }
                        }
                    }
                }
                
                
                a : for stave in staves {
                    if stave.staveIndex == staff {
                        for v in stave.voices {
                            for note in v.notes {
                                if note.tick == tick && !(self.measureIndex == 1 && tick == 0) {
                                    if type == "sym" {
                                        self.segnoStaff = dir["staff"].intValue;
                                        if text == "segno" {
                                            self.segnoType = 1;
                                        }else if text == "coda" {
                                            //                                            self.segnoType = 2;
                                        }
                                        break a;
                                    }else if type.count == 0 {
                                        if text == "D.S. al Coda" {
                                            self.segnoType = 2;
                                        }else if text == "To Coda" {
                                            self.segnoType = 3;
                                        }else if text == "Coda" {
                                            self.segnoType = 4;
                                        }else if text.contains("rit.") {
                                            note.word += text;
                                        }else {
                                            if text.count > 1 {
                                                if NSString(string: text).substring(to: 1) != "." {
                                                    note.word += text;
                                                }
                                            }else{
                                                note.word += text;
                                            }
                                        }
                                        break a;
                                    }else if type == "metronome" {
                                        note.metronome = dir["value"].stringValue;
                                        let textl = dir["textl"].stringValue;
                                        if textl.count != 0 {
                                            note.word = textl;
                                        }
                                        if dir["value"].stringValue.count == 0 && dir["textl"].stringValue.count == 0 {
                                            for dir in dirs {
                                                let type = dir["type"].stringValue;
                                                let text = dir["text"].stringValue;
                                                if type.count == 0 && text.contains("=") {
                                                    note.metronome = text.replacingOccurrences(of: "=", with: "").replacingOccurrences(of: " ", with: "");
                                                    break a;
                                                }
                                            }
                                        }
                                        break a;
                                    }
                                    
                                }
                            }
                        }
                        
                        if type == "dyn" {
                            var isAdd = false;
                            for v in stave.voices {
                                for note in v.notes {
                                    let paramX = dir["param"].dictionary?["x"]?.doubleValue ?? 0;
                                    if paramX < note.x + 10 {
                                        note.dynString = dir["text"].stringValue;
                                        isAdd = true;
                                        break a;
                                    }
                                }
                            }
                            if !isAdd {
                                stave.voices.first?.notes.last?.dynString = dir["text"].stringValue;
                            }
                        }else if type == "pedal" {
                            let paramX = dir["param"].dictionary?["x"]?.doubleValue ?? 0;
                            let direction = ShmNoteDirectionModel();
                            let line = dir["line"].boolValue;
                            direction.x = paramX;
                            direction.pedal = text;
                            direction.voice = "\(1)";
                            direction.staff = "\(stave.staveIndex)";
                            direction.isPedalLine = line;
                            if paramX < self.w {
                                stave.voices.first?.directions.append(direction);
                            }else{
                                stave.voices.first?.moreDirections.append(direction);
                            }
                            
                        }
                    }
                }
            }
        }
        
        if self.measureIndex > 1 {
            for stave in self.staves {
                for v in stave.voices {
                    if let note = v.notes.first {
                        if note.tick > 0 {
                            var duration = Double(note.tick) / 480;
                            var count = 0;
                            var tick = 0;
                            while duration > 0 {
                                let restNote = InsCcNote(json: JSON());
                                restNote.staff = note.staff;
                                restNote.v = note.v;
                                restNote.tick = tick;
                                restNote.rest = true;
                                if duration >= 4 {
                                    restNote.type = 1;
                                    duration -= 4;
                                }else if duration >= 2 {
                                    restNote.type = 2;
                                    duration -= 2;
                                }else if duration >= 1 {
                                    restNote.type = 4;
                                    duration -= 1;
                                }else if duration >= 0.5 {
                                    restNote.type = 8;
                                    duration -= 0.5;
                                }else if duration >= 0.25 {
                                    restNote.type = 16;
                                    duration -= 0.25;
                                }else if duration >= 0.125 {
                                    restNote.type = 32;
                                    duration -= 0.125;
                                }else{
                                    restNote.type = 64;
                                    duration -= 0.0625;
                                }
                                restNote.duration = 4.0/Double(restNote.type);
                                tick += Int(restNote.duration) * 480;
                                if note.clef.count != 0 {
                                    restNote.clef = note.clef;
                                    note.clef = "";
                                }
                                v.notes.insert(restNote, at: count);
                                count += 1;
                            }
                            
                        }
                    }
                }
            }
        }
        
        if self.measureIndex > 1 {
            if self.measureIndex == 36 {
                //                print(111);
            }
            for stave in self.staves {
                for v in stave.voices {
                    var newNotes = [InsCcNote]()
                    for (i , note) in v.notes.enumerated() {
                        var tick = 0;
                        var lastTick = 0;
                        if i == 0 {
                            tick = note.tick;
                        }else {
                            lastTick = (v.notes[i - 1].tick + Int(v.notes[i - 1].duration * 480.0));
                            tick = note.tick - lastTick;
                        }
                        //                        print("tick" , tick , lastTick , note.tick);
                        if tick > 90 {
                            var duration = Double(tick) / 480;
                            while duration > 0 {
                                let restNote = InsCcNote(json: JSON());
                                restNote.staff = note.staff;
                                restNote.v = note.v;
                                restNote.tick = lastTick;
                                restNote.rest = true;
                                if duration >= 4 {
                                    restNote.type = 1;
                                    duration -= 4;
                                    lastTick += 4 * 480;
                                }else if duration >= 2 {
                                    restNote.type = 2;
                                    duration -= 2;
                                    lastTick += 2 * 480;
                                }else if duration >= 1 {
                                    restNote.type = 4;
                                    duration -= 1;
                                    lastTick += 1 * 480;
                                }else if duration >= 0.5 {
                                    restNote.type = 8;
                                    duration -= 0.5;
                                    lastTick += Int(0.5 * 480);
                                }else if duration >= 0.25 {
                                    restNote.type = 16;
                                    duration -= 0.25;
                                    lastTick += Int(0.25 * 480);
                                }else if duration >= 0.125 {
                                    restNote.type = 32;
                                    duration -= 0.125;
                                    lastTick += Int(0.125 * 480);
                                }else{
                                    restNote.type = 64;
                                    duration -= 0.0625;
                                    lastTick += Int(0.0625 * 480);
                                }
                                restNote.duration = 4.0/Double(restNote.type);
                                //                                tick += Int(restNote.duration) * 480;
                                if note.clef.count != 0 {
                                    restNote.clef = note.clef;
                                    note.clef = "";
                                }
                                newNotes.append(restNote);
                            }
                            
                        }
                        
                        newNotes.append(note);
                    }
                    v.notes = newNotes;
                    
                }
            }
        }
        
        
        
        
        if let harmonys = json["harmonys"].array {
            for harmony in harmonys {
                let model = ShmHarmonysModel();
                model.x = harmony["x"].doubleValue;
                model.defaulty = harmony["y"].intValue;
                model.staff = 1;
                model.kind = harmony["kind"].dictionary?["type"]?.stringValue ?? "";
                model.rootstep = harmony["root"].dictionary?["step"]?.stringValue ?? "";
                self.staves.first?.voices.first?.directions.append(model);
            }
        }
    }
}
